﻿
Imports std

Public Class [for]
    Inherits sentence

    Public Const [for] As String = "for"
    Public Const conditionStart As Char = character.leftBracket
    Public Const conditionEnd As Char = character.rightBracket
    Public Const conditionSeparator As Char = character.semicolon

    Protected Friend Shared Shadows Function _isMeaningfulMark(ByVal c As Char) As Boolean
        Return isConditionStart(c) OrElse isConditionSeparator(c) OrElse isConditionEnd(c)
    End Function

    Private statusStart As value_clause = Nothing
    Private statusEnd As value = Nothing
    Private statusUpdate As value_clause = Nothing
    Private para As paragraph = Nothing

    Private Sub New(ByVal istart As value_clause, ByVal iend As value, ByVal iupdate As value_clause, _
                    ByVal ipara As paragraph)
        statusStart = istart
        statusEnd = iend
        statusUpdate = iupdate
        para = ipara
    End Sub

    Private Function finish(ByVal ctx As context) As ternary
        Dim v As bare_variable = Nothing
        If Not statusEnd.invoke(ctx, v) Then
            Return ternary.unknown
        ElseIf v.false() Then
            Return ternary.true
        Else
            Return ternary.false
        End If
    End Function

    Protected Overrides Function invokeImpl(ByVal ctx As context) As Boolean
        assert(Not ctx Is Nothing, "ctx is nothing.")

        If statusStart.invoke(ctx) Then
            Dim f As ternary = ternary.unknown
            f = finish(ctx)
            While f = ternary.false
                If Not (para.invoke(ctx) AndAlso statusUpdate.invoke(ctx)) Then
                    Return False
                End If
                f = finish(ctx)
            End While
            If f = ternary.unknown Then
                Return False
            Else
                Return True
            End If
        Else
            Return False
        End If
    End Function

    Private Shared Function forstart(ByVal s As String, ByVal index As Int64, ByRef inc As Int64) As Boolean
        If strsame(s, index, [for], 0, strlen([for])) Then
            inc = strlen([for])
            Return True
        Else
            Return False
        End If
    End Function

    Private Shared Function isConditionStart(ByVal c As Char) As Boolean
        Return c = conditionStart
    End Function

    Private Shared Function isConditionSeparator(ByVal c As Char) As Boolean
        Return c = conditionSeparator
    End Function

    Private Shared Function isConditionEnd(ByVal c As Char) As Boolean
        Return c = conditionEnd
    End Function

    Private Shared Function parseImpl(ByVal input As String, ByRef index As Int64, _
                                      ByRef output As [for]) As Boolean
        If token(input, index, Nothing, AddressOf forstart, AddressOf [false]) AndAlso _
           token(input, index, Nothing, AddressOf isConditionStart, AddressOf [false]) Then
            Dim statusStart As value_clause = Nothing
            If value_clause.parse(input, index, statusStart) AndAlso _
               token(input, index, Nothing, AddressOf isConditionSeparator, AddressOf [false]) Then
                Dim statusEnd As value = Nothing
                If value.parse(input, index, statusEnd) AndAlso _
                   token(input, index, Nothing, AddressOf isConditionSeparator, AddressOf [false]) Then
                    Dim statusUpdate As value_clause = Nothing
                    If value_clause.parse(input, index, statusUpdate) AndAlso _
                       token(input, index, Nothing, AddressOf isConditionEnd, AddressOf [false]) Then
                        Dim para As paragraph = Nothing
                        If paragraph.parse(input, index, para) Then
                            output = New [for](statusStart, statusEnd, statusUpdate, para)
                            Return True
                        End If
                    End If
                End If
            End If
        End If

        Return False
    End Function

    Protected Overrides Sub setsource(ByVal script As String, ByVal start As Long, ByVal [end] As Long)
        setsourceImpl([for] + conditionStart + statusStart.scriptSource() + conditionSeparator + _
                      statusEnd.scriptSource() + conditionSeparator + statusUpdate.scriptSource() + conditionEnd, _
                      start, [end])
    End Sub

    Public Shared Shadows Function parse(ByVal input As String, ByRef index As Int64, _
                                         ByRef output As [for]) As Boolean
        Return parsebase(input, index, output, AddressOf parseImpl)
    End Function
End Class
